import jwt
from jwt.exceptions import InvalidSignatureError, ExpiredSignatureError

from apps.a_common.log import MyLogger
from apps.a_common.permission import AnonymousUser
from apps.users.helper import get_user_by_id
from config import JWT_SECRET_KEY, JWT_ALGORITHM, JWT_EXP_CLAIM, JWT_USER_ID_CLAIM
from utils.time import int_timestamp

logger = MyLogger('jwt auth')
TIMEOUT = 60 * 60


def decode_token(token) -> (dict, bool):
    try:
        return jwt.decode(token, JWT_SECRET_KEY, algorithms=[JWT_ALGORITHM, ]), True
    except InvalidSignatureError:
        logger.info('decode jwt fail, detail: {}'.format(token))
        return {}, False
    except ExpiredSignatureError:
        logger.info('token expire')
        return {}, False
    except Exception as e:
        logger.error(f"unknown jwt decode error: {str(e)}")
        return {}, False


def encode_token(user_id):
    payload = {
        JWT_USER_ID_CLAIM: user_id,
        JWT_EXP_CLAIM: int_timestamp() + TIMEOUT,
    }
    return jwt.encode(payload, JWT_SECRET_KEY, algorithm=JWT_ALGORITHM)


class Token:
    def __init__(self, token):
        self.token = token
        self.payload, self.decode_success = decode_token(token)

    def get_user(self):
        if not self.decode_success:
            return AnonymousUser()
        user_id = self.get_user_id()
        logger.info(f'try to get user by id {user_id}')
        user = get_user_by_id(user_id)
        logger.info(f'get user: {user}, user_id: {user.id}')
        return user

    def get_user_id(self):
        return self.payload[JWT_USER_ID_CLAIM]
